#include "GY_StencilGroup.h"
#include <QDebug>
#include <QGraphicsPathItem>
#include "Graphics/GY_GraphicsReflection.h"

GY_StencilGroup::GY_StencilGroup(const QString &guid, QGraphicsItem *parent) : GY_ContainerTransform(guid,this, parent)
{
    initializationPropertyInfo();
    this->setCenterPointF(m_PropertyInfoMap["Position"].propertyValue.toPointF());
    m_pClippingToolContainer = new GY_ClippingToolContainer(QString("%1_Tool").arg(guid),this);
    m_ChildrensMap.insert(m_pClippingToolContainer->getGuid(),m_pClippingToolContainer);
    this->addToGroup(m_pClippingToolContainer);
    updateDraw();
}

GY_StencilGroup::~GY_StencilGroup()
{

}

bool GY_StencilGroup::addItem(GY_Object *pItem)
{
    m_pClippingToolContainer->addItem((GY_Object*)pItem);
    m_ItemVector.append(pItem);
    if(pItem->inherits("GY_BasicsGraphicsObject"))
    {
        ((GY_BasicsGraphicsObject *)pItem)->setZValue(m_Size++);
    }
    else if(pItem->inherits("GY_ContainerTransform"))
    {
        ((GY_ContainerTransform *)pItem)->setZValue(m_Size++);
    }
    updateDraw();
    return true;
}

GY_Object *GY_StencilGroup::copyItem(const QString &guid)
{
    if(getUserData(GY_ENUM::IsCopy) == 1) {
//        return nullptr;
        GY_Object *tmp;
        this->copyItemSig(&tmp);
        //更新copyItem属性列表
        QMap<QString,GY_PropertyInfo>::Iterator iterProperty = m_PropertyInfoMap.begin();
        while (iterProperty != m_PropertyInfoMap.end()) {
            if(((iterProperty.value().updateType)&PointOfRelative) == PointOfRelative) {
                tmp->updateProperty(iterProperty.key(), submittingPropertyValues(iterProperty.value().updateType,iterProperty.value().propertyValue,this));
            }else if(((iterProperty.value().updateType)&NotUpdate) == NotUpdate){
                ++iterProperty;
                continue;
            }else {
                tmp->updateProperty(iterProperty.key(), iterProperty.value().propertyValue);
            }
            ++iterProperty;
        }
        return tmp;
    }
    GY_Object* pObj;
    if(guid.isEmpty()) {
        pObj = (GY_Object*)GY_GraphicsReflection::getInstance()->newInstanceObjectClass(this->metaObject()->className(),this->getGuid()+"-"+QString::number(m_MyGuid));
        m_MyGuid++;
    }else {
        pObj = (GY_Object*)GY_GraphicsReflection::getInstance()->newInstanceObjectClass(this->metaObject()->className(),guid);
    }
    if(pObj == nullptr) {
        qDebug()<<this->getGuid()<<"isEmpty";
        return nullptr;
    }
    QVector<GY_Object *> childrens = m_pClippingToolContainer->getOrderChildrens();
    int childrensSize = childrens.size();
    for(int i=0;i<childrensSize;i++) {
//        if(childrens[i]->copyItem() == nullptr) {
//            qDebug()<<childrens[i]->getGuid()<<"isEmpty";
//            continue;
//        }
        ((GY_ContainerTransform*)pObj)->addItem(childrens[i]->copyItem());
    }

    QMap<QString,GY_PropertyInfo>::Iterator iterProperty = m_PropertyInfoMap.begin();
    while (iterProperty != m_PropertyInfoMap.end()) {
        if(((iterProperty.value().updateType)&PointOfRelative) == PointOfRelative) {
            pObj->updateProperty(iterProperty.key(), submittingPropertyValues(iterProperty.value().updateType,iterProperty.value().propertyValue,this));
        }else if(((iterProperty.value().updateType)&NotUpdate) == NotUpdate){
            ++iterProperty;
            continue;
        }else {
            pObj->updateProperty(iterProperty.key(), iterProperty.value().propertyValue);
        }
        ++iterProperty;
    }
    connect(pObj,&GY_Object::copyItemSig,this,&GY_Object::originalVersion);
    pObj->setUserData(GY_ENUM::IsCopy, QVariant::fromValue(1));
    return pObj;
}

bool GY_StencilGroup::removItem(const QString &guid)
{
    return m_pClippingToolContainer->removItem(guid);
}

bool GY_StencilGroup::removItem(const GY_Object *pItem)
{
    bool remove = m_pClippingToolContainer->removItem((GY_Object*)pItem);
    this->GY_ContainerTransform::removItem((GY_Object*)pItem);
    m_ItemVector.removeOne((GY_Object*)pItem);
    if(pItem->inherits("GY_BasicsGraphicsObject"))
    {
        ((GY_BasicsGraphicsObject *)pItem)->setZValue(0);
    }
    else if(pItem->inherits("GY_ContainerTransform"))
    {
        ((GY_ContainerTransform *)pItem)->setZValue(0);
    }
    updateDraw();
    return remove;
}

QVariant GY_StencilGroup::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{
    updateDraw();
    return QGraphicsItem::itemChange(change,value);
}

void GY_StencilGroup::initializationPropertyInfo()
{
    GY_PropertyInfo ObjectName(this);
    ObjectName.propertyName = "ObjectName";
    ObjectName.propertyValue = QString();
    ObjectName.updateType = Update|OrdinaryAttributes;
    ObjectName.propertyType = QStringPropertyType;
    ObjectName.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_StencilGroup::updateObjectName;
    m_PropertyInfoMap.insert("ObjectName",ObjectName);
    m_PropertyInfoMap[ObjectName.propertyName].setConnect();

    //位置
    GY_PropertyInfo positonPropertyInfo(this);
    positonPropertyInfo.propertyName="Position";
    positonPropertyInfo.propertyValue=QPointF(0,0);
    positonPropertyInfo.updateType = Update|MoveUpdate|PointOfRelative;
    positonPropertyInfo.propertyType = PointPropertyType;
    positonPropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_StencilGroup::updatePosition;
    m_PropertyInfoMap.insert(positonPropertyInfo.propertyName,positonPropertyInfo);
    m_PropertyInfoMap[positonPropertyInfo.propertyName].setConnect();

    //隐藏
    GY_PropertyInfo isVisiblePropertyInfo(this);
    isVisiblePropertyInfo.propertyName="IsVisible";
    isVisiblePropertyInfo.propertyValue=true;
    isVisiblePropertyInfo.updateType = Update|OrdinaryAttributes;
    isVisiblePropertyInfo.propertyType = BoolPropertyType;
    isVisiblePropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_StencilGroup::updateIsVisible;
    m_PropertyInfoMap.insert(isVisiblePropertyInfo.propertyName,isVisiblePropertyInfo);
    m_PropertyInfoMap[isVisiblePropertyInfo.propertyName].setConnect();

    GY_PropertyInfo EnableStencilPropertyInfo(this);
    EnableStencilPropertyInfo.propertyName="EnableStencil";
    EnableStencilPropertyInfo.propertyValue=true;
    EnableStencilPropertyInfo.updateType = Update|OrdinaryAttributes;
    EnableStencilPropertyInfo.propertyType = BoolPropertyType;
    EnableStencilPropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_StencilGroup::updateEnableStencil;
    m_PropertyInfoMap.insert(EnableStencilPropertyInfo.propertyName,EnableStencilPropertyInfo);
    m_PropertyInfoMap[EnableStencilPropertyInfo.propertyName].setConnect();

    GY_PropertyInfo InvertStencilPropertyInfo(this);
    InvertStencilPropertyInfo.propertyName="InvertStencil";
    InvertStencilPropertyInfo.propertyValue=true;
    InvertStencilPropertyInfo.updateType = Update|OrdinaryAttributes;
    InvertStencilPropertyInfo.propertyType = BoolPropertyType;
    InvertStencilPropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_StencilGroup::updateInvertStencil;
    m_PropertyInfoMap.insert(InvertStencilPropertyInfo.propertyName,InvertStencilPropertyInfo);
    m_PropertyInfoMap[InvertStencilPropertyInfo.propertyName].setConnect();

}

bool GY_StencilGroup::updatePosition(const QString &name, const QVariant &value)
{
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    //setpos设置为父级坐标
    QPointF point = value.toPointF();
    if(this->parentItem()) {
        point = this->mapToParent(this->mapFromScene(value.toPointF()));
    }
    this->setPos(point);
    m_PropertyInfoMap[name].propertyValue=this->mapFromScene(value.toPointF());
    return true;
}

bool GY_StencilGroup::updateIsVisible(const QString &name, const QVariant &value)
{
    if(!value.canConvert<bool>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue=value;
    this->setVisible(value.toBool());
    return true;
}

bool GY_StencilGroup::updateEnableStencil(const QString &name, const QVariant &value)
{
    if(!value.canConvert<bool>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue=value;
    updateDraw();
    return true;
}

bool GY_StencilGroup::updateInvertStencil(const QString &name, const QVariant &value)
{
    if(!value.canConvert<bool>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue=value;
    updateDraw();
    return true;
}

void GY_StencilGroup::updateDraw()
{
    if(m_ItemVector.size()<=0)
    {
        return;
    }
    if(m_PropertyInfoMap["EnableStencil"].propertyValue.toBool()) {
        m_pClippingToolContainer->setIsCut(m_PropertyInfoMap["EnableStencil"].propertyValue.toBool());
    }
    //第一个图形的path
    QPainterPath basePath;
    if(m_ItemVector.at(0)->inherits("GY_BasicsGraphicsObject"))
    {
        basePath=((GY_BasicsGraphicsObject*)m_ItemVector.at(0))->shape();
    }
    else if(m_ItemVector.at(0)->inherits("GY_ContainerTransform"))
    {
        basePath=((GY_ContainerTransform*)m_ItemVector.at(0))->getPath();
    }
    basePath=m_ItemVector.at(0)->getGraphicsItem()->mapToParent(basePath);
    //所以图的path
    QPainterPath allPath=basePath;
    //用于汇总所有的path
    QPainterPath summaryPath;
    for(int i=1;i<m_ItemVector.size();i++) {
        if(m_ItemVector.at(i)->inherits("GY_BasicsGraphicsObject"))
        {
            allPath +=m_ItemVector.at(i)->getGraphicsItem()->mapToParent(m_ItemVector.at(i)->getGraphicsItem()->shape());
            summaryPath = summaryPath+(basePath&m_ItemVector.at(i)->getGraphicsItem()->mapToParent(m_ItemVector.at(i)->getGraphicsItem()->shape()));
        }
        else if(m_ItemVector.at(i)->inherits("GY_ContainerTransform"))
        {
            allPath +=m_ItemVector.at(i)->getGraphicsItem()->mapToParent(((GY_ContainerTransform*)m_ItemVector.at(i))->getPath());
            summaryPath+=(basePath&m_ItemVector.at(i)->getGraphicsItem()->mapToParent(((GY_ContainerTransform*)m_ItemVector.at(i))->getPath()));
        }
    }
    if(!m_PropertyInfoMap["EnableStencil"].propertyValue.toBool()) {
        m_pClippingToolContainer->setShape(allPath-basePath+summaryPath);
        return;
    }
    if(m_PropertyInfoMap["InvertStencil"].propertyValue.toBool()) {
        m_pClippingToolContainer->setShape(allPath-basePath);
    }else {
        m_pClippingToolContainer->setShape(summaryPath);
    }
}



